﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeAngel.Domain.Framework
{
    #region RequiredValueRule

    /// <summary>
    /// Identifies that a value of a property is required (i.e. the value of that property cannot be null).
    /// </summary>
    public class RequiredValueRule : ValuePropertyRule
    {

        public RequiredValueRule(IValueProperty ValueProperty) : base(ValueProperty) { }

        /// <summary>
        /// Identifies the name of this rule suitable for displaying to an end user.
        /// </summary>
        public override string Name { get { return "Required Value"; } }

        /// <summary>
        /// Identifies a description of this rule suitable for displaying to an end user.
        /// </summary>
        public override string Description
        {
            get { return this.ValueProperty.FriendlyName + " is a required value."; }
        }

        /// <summary>
        /// Describes the rule violation, if this rule is currently invalid.
        /// </summary>
        public override string ViolationDescription
        {
            get { return this.Description; }
        }

        /// <summary>
        /// Determines if the identified value is valid for this rule.
        /// </summary>
        public override bool IsValueValid(object value)
        {
            if (value is string)
                return !string.IsNullOrWhiteSpace(value as string);
            else
                return (value != null);
        }

        /// <summary>
        /// Determines if this rule is currently valid.
        /// </summary>
        public override bool IsValid()
        {
            return this.IsValueValid(this.ValueProperty.GetValue());
        }
    }

    #endregion

    // TODO: Implement MaximumLengthRule
    //#region MaximumLengthRule

    ///// <summary>
    ///// Requires the value of an associated string property be less than or equal to a certain length.
    ///// </summary>
    //public class MaximumLengthRule : ValuePropertyRule
    //{

    //    public MaximumLengthRule(Properties.StringProperty stringProperty, int maximumLength)
    //        : base(stringProperty)
    //    {
    //        this.mMaximumLength = maximumLength;
    //    }

    //    private int MaximumLength
    //    {
    //        get { return this.mMaximumLength; }
    //    }
    //    private int mMaximumLength;

    //    public override string Name
    //    {
    //        get { return "Maximum Length"; }
    //    }

    //    public override string Description
    //    {
    //        get { return "The length of property '" + base.ValueProperty.Name + "' cannot be longer than " + this.mMaximumLength + " characters."; }
    //    }

    //    public override void Validate()
    //    {
    //        if (!this.IsValueValid(base.ValueProperty.Value)) base.ThrowRuleException();
    //    }

    //    public override bool IsValueValid(object value)
    //    {
    //        if ((value == null)) return true;
    //        if (!value is string) return false;
    //        return Strings.Len(value) <= this.mMaximumLength;
    //    }

    //    public override string ViolationDescription
    //    {
    //        get { return "The length of property '" + base.ValueProperty.Name + "' cannot be longer than " + this.mMaximumLength + " characters. Current Length: " + base.ValueProperty.ToString.Length; }
    //    }

    //}

    //#endregion


    // TODO: Implement RangeRule
    ///// <summary>
    ///// Requires that a single value property be between two values.
    ///// </summary>
    ///// <Remarks>May allow or disallow Null values. May be inclusive or exclusive.</Remarks>
    //public class RangeRule : ValuePropertyRule
    //{

    //    public RangeRule(ValueProperty ValueProperty)
    //        : base(ValueProperty)
    //    {
    //    }

    //    public object LowerBound
    //    {
    //        get { return this.mLowerBound; }
    //        set { this.mLowerBound = value; }
    //    }
    //    private object mLowerBound;

    //    public object UpperBound
    //    {
    //        get { return this.mUpperBound; }
    //        set { this.mUpperBound = value; }
    //    }
    //    private object mUpperBound;

    //    /// <summary>
    //    /// Identifies whether or not a Null value violates this rule.
    //    /// </summary>
    //    public bool NullIsAcceptable
    //    {
    //        get { return this.mNullIsAcceptable; }
    //        set { this.mNullIsAcceptable = value; }
    //    }
    //    private bool mNullIsAcceptable;

    //    /// <summary>
    //    /// Identnfies if the valid range includes the upper and lower bounds.
    //    /// </summary>
    //    public bool Inclusive
    //    {
    //        get { return this.mInclusive; }
    //        set { this.mInclusive = value; }
    //    }
    //    private bool mInclusive;

    //    public override string Name
    //    {
    //        get { return "Range Rule"; }
    //    }

    //    public override string Description
    //    {
    //        get { return base.ValueProperty.UserFriendlyName + " must be between " + this.mLowerBound.ToString + " and " + this.mUpperBound.ToString + ". " + (this.mInclusive ? "(Inclusive)" : "(Exclusive)") + " " + (this.mNullIsAcceptable ? "(Can be Null)" : "(Can not be Null)"); }
    //    }

    //    public override void Validate()
    //    {
    //        object Value = null;
    //        if (base.ValueProperty.IsNotNull) Value = base.ValueProperty.Value;
    //        if (!this.IsValueValid(Value)) this.ThrowRuleException();
    //    }

    //    /// <summary>
    //    /// Determines if the identified value satisfies this rule.
    //    /// </summary>
    //    /// <Returns>Returns True if it does; otherwise False.</Returns>
    //    public override bool IsValueValid(object value)
    //    {
    //        if ((value == null))
    //        {
    //            if (this.mNullIsAcceptable)
    //            {
    //                return true;
    //            }
    //            else
    //            {
    //                return false;

    //            }
    //        }
    //        else
    //        {
    //            if (this.mInclusive)
    //            {
    //                return this.mLowerBound <= value && value <= this.mUpperBound;
    //            }
    //            else
    //            {
    //                return this.mLowerBound < value && value < this.mUpperBound;
    //            }

    //        }
    //    }

    //    public override string ViolationDescription
    //    {
    //        get
    //        {
    //            if (base.ValueProperty.IsNull)
    //            {
    //                return this.Description + Environment.NewLine + "Current Value: Null";
    //            }
    //            else
    //            {
    //                return this.Description + Environment.NewLine + "Current Value: " + base.ValueProperty.Value.ToString;
    //            }
    //        }
    //    }

    //}
}
